package com.yupi.yoj.controller;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.yupi.yoj.annotation.AuthCheck;
import com.yupi.yoj.common.BaseResponse;
import com.yupi.yoj.common.ErrorCode;
import com.yupi.yoj.common.ResultUtils;
import com.yupi.yoj.constant.QueueConstant;
import com.yupi.yoj.constant.UserConstant;
import com.yupi.yoj.exception.BusinessException;
import com.yupi.yoj.exception.ThrowUtils;
import com.yupi.yoj.judge.codesandbox.model.ExecuteCodeRequest;
import com.yupi.yoj.model.dto.questionsubmit.AddQuestionSubmitRequest;
import com.yupi.yoj.model.dto.questionsubmit.QuestionSubmitQueryRequest;
import com.yupi.yoj.model.dto.questionsubmit.QuestionSubmitVO;
import com.yupi.yoj.model.dto.questionsubmit.UpdateQuestionSubmitRequestById;
import com.yupi.yoj.model.entity.JudgeCase;
import com.yupi.yoj.model.entity.QuestionSubmit;
import com.yupi.yoj.model.vo.QuestionVO;
import com.yupi.yoj.service.QuestionService;
import com.yupi.yoj.service.QuestionSubmitService;
import org.apache.commons.collections4.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RMap;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Set;

@RestController
@RequestMapping("/questionSubmit")
public class QuestionSubmitController {

    @Autowired
    QuestionSubmitService questionSubmitService;

    @Autowired
    QuestionService questionService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 提交题目
     * @param addQuestionSubmitRequest
     * @return
     */
    @PostMapping("/add") // todo 限流
    @AuthCheck(mustRole = UserConstant.USER_LOGIN_STATE)
    BaseResponse<QuestionSubmitVO> addQuestionSubmit(AddQuestionSubmitRequest addQuestionSubmitRequest) {
         ThrowUtils.throwIf(addQuestionSubmitRequest == null, ErrorCode.PARAMS_ERROR, "参数为空");
         String language = addQuestionSubmitRequest.getLanguage();
         String code = addQuestionSubmitRequest.getCode();

         Long questionid = addQuestionSubmitRequest.getQuestionid();
         Long userid = addQuestionSubmitRequest.getUserid();

         ThrowUtils.throwIf(questionid <= 0 || userid <= 0, ErrorCode.PARAMS_ERROR, "参数错误");

         // 查题目是否存在
        QuestionVO questionById = questionService.getQuestionById(questionid);
        if (questionById == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "题目不存在！");
        }
        if (StringUtils.isAnyBlank( language, code)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        QuestionSubmit questionSubmit = new QuestionSubmit();
        BeanUtils.copyProperties(addQuestionSubmitRequest, questionSubmit);
        Long id = questionSubmitService.addQuestionSubmit(questionSubmit);
        questionSubmit.setId(id);

        // todo 添加消息到消息队列 添加以后，修改提交状态为'判题中' MQ处理以后，修改状态为成功或失败
        rabbitTemplate.convertAndSend(QueueConstant.QUEUE_NAME, String.valueOf(id));

        // 向redis中添加提交记录
        questionSubmitService.addQuestionSubmitTimes(userid);

        QuestionSubmitVO questionSubmitVO = new QuestionSubmitVO();
        BeanUtils.copyProperties(questionSubmit, questionSubmitVO);
        return ResultUtils.success(questionSubmitVO);
    }

    @PutMapping("/update")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    BaseResponse<Boolean> updateQuestionSubmitById(UpdateQuestionSubmitRequestById updateQuestionSubmitRequestById ){
        ThrowUtils.throwIf(updateQuestionSubmitRequestById == null, ErrorCode.PARAMS_ERROR, "参数为空");
        Long id = updateQuestionSubmitRequestById.getId();
        String language = updateQuestionSubmitRequestById.getLanguage();
        String code = updateQuestionSubmitRequestById.getCode();
        Long questionId = updateQuestionSubmitRequestById.getQuestionid();
        Long userId = updateQuestionSubmitRequestById.getUserid();

        if (id <= 0 || questionId <= 0 || userId <= 0 || StringUtils.isAnyBlank( language, code)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        QuestionSubmit questionSubmit = new QuestionSubmit();
        BeanUtils.copyProperties(updateQuestionSubmitRequestById, questionSubmit);
        questionSubmitService.updateQuestionSubmitById(questionSubmit);
        return ResultUtils.success(true);
    }

    @DeleteMapping("/delete/{id}")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    BaseResponse<Boolean> deleteQuestionSubmitById(@PathVariable("id") Long id) {
        if (id == null) throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        questionSubmitService.deleteQuestionSubmitById(id);
        return ResultUtils.success(true);
    }

    @GetMapping("/get/uid/{uid}")
    BaseResponse<List<QuestionSubmitVO>> getQuestionSubmitByUId(@PathVariable("uid") Long uid ) {
        if (uid == null) throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        List<QuestionSubmitVO> questionSubmitVOList = questionSubmitService.getQuestionSubmitByUId(uid);
        if (questionSubmitVOList == null) throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "题目不存在");
        return ResultUtils.success(questionSubmitVOList);
    }

    @GetMapping("/get/{uid}/{qid}")
    BaseResponse<List<QuestionSubmitVO>> getQuestionSubmitByUIdQId(@PathVariable("uid") Long uid, @PathVariable("qid") Long qid) {
        if (uid == null || uid <= 0 || qid == null || qid <= 0) throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        List<QuestionSubmitVO> questionSubmitVOList = questionSubmitService.getQuestionSubmitByUIdQId(uid, qid);
        if (questionSubmitVOList == null) throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "题目不存在");
        return ResultUtils.success(questionSubmitVOList);
    }

    @PostMapping("/list")
    public BaseResponse<List<QuestionSubmitVO>> listQuestionSubmit() throws JsonProcessingException {
        List<QuestionSubmit> questionSubmitList = questionSubmitService.list();
        ThrowUtils.throwIf(questionSubmitList==null, ErrorCode.NOT_FOUND_ERROR, "题目库为空");
        List<QuestionSubmitVO> questionSubmitVOList = questionSubmitService.getQuestionSubmitVO(questionSubmitList);
        return ResultUtils.success(questionSubmitVOList);
    }

    /**
     * 分页获取用户列表（仅管理员）
     *
     * @param questionSubmitQueryRequest
     * @param request
     * @return
     */
    @PostMapping("/list/page")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Page<QuestionSubmitVO>> listQuestionSubmitByPage(@RequestBody QuestionSubmitQueryRequest questionSubmitQueryRequest,
                                                   HttpServletRequest request) {
        if (questionSubmitQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long current = questionSubmitQueryRequest.getCurrent();
        long size = questionSubmitQueryRequest.getPageSize();
        // 限制爬虫
        ThrowUtils.throwIf(size <= 0, ErrorCode.PARAMS_ERROR);
        Page<QuestionSubmit> questionSubmitPage = questionSubmitService.page(new Page<>(current, size),
                questionSubmitService.getQueryWrapper(questionSubmitQueryRequest));
        Page<QuestionSubmitVO> userVOPage = new Page<>(current, size, questionSubmitPage.getTotal());
        List<QuestionSubmitVO> userVO = questionSubmitService.getQuestionSubmitVO(questionSubmitPage.getRecords());
        userVOPage.setRecords(userVO);
        return ResultUtils.success(userVOPage);
    }

    /**
     * 分页获取用户封装列表
     *
     * @param questionSubmitQueryRequest
     * @param request
     * @return
     */
    @PostMapping("/list/page/vo")
    public BaseResponse<Page<QuestionSubmitVO>> listQuestionSubmitVOByPage(@RequestBody QuestionSubmitQueryRequest questionSubmitQueryRequest,
                                                       HttpServletRequest request) throws JsonProcessingException {
        if (questionSubmitQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long current = questionSubmitQueryRequest.getCurrent();
        long size = questionSubmitQueryRequest.getPageSize();
        // 限制爬虫
        ThrowUtils.throwIf(size <= 0, ErrorCode.PARAMS_ERROR);
        Page<QuestionSubmit> questionSubmitPage = questionSubmitService.page(new Page<>(current, size),
        questionSubmitService.getQueryWrapper(questionSubmitQueryRequest));
        Page<QuestionSubmitVO> questionSubmitVOPage = new Page<>(current, size, questionSubmitPage.getTotal());
        List<QuestionSubmitVO> questionSubmitVO = questionSubmitService.getQuestionSubmitVO(questionSubmitPage.getRecords());
        questionSubmitVOPage.setRecords(questionSubmitVO);
        return ResultUtils.success(questionSubmitVOPage);
    }

    /**
     * 读取上传文件 返回内容
     */
    @PostMapping("/readFile")
    public BaseResponse<String> readFile(@RequestParam(value = "file") MultipartFile[] file) {
        String fileContent = questionSubmitService.readFile(file[0]);
        return ResultUtils.success(fileContent);
    }

    /**
     * 根据id查提交信息
     */
    @GetMapping("/get/qid/{id}")
    public BaseResponse<QuestionSubmitVO> getQuestionSubmitVOById(@PathVariable("id") Long id) {
        QuestionSubmitVO questionSubmitVO = questionSubmitService.getQuestionSubmitVOById(id);
        return ResultUtils.success(questionSubmitVO);
    }


    /**
     * 获取这一年的提交次数
     */
    @GetMapping("/get/submitCount/{userid}")
    public BaseResponse<Set<Map.Entry<Integer, Integer>>> getSubmitCountByYear(@PathVariable("userid") Long userid) {
        ThrowUtils.throwIf(userid == null || userid <= 0, ErrorCode.PARAMS_ERROR, "用户id错误");
        RMap<Integer, Integer> submitQuestionTimesYear = questionSubmitService.getSubmitCountByYear(userid);
        HashedMap<Integer, Integer> integerIntegerHashedMap = new HashedMap<>();
        for (Map.Entry<Integer, Integer> entry : submitQuestionTimesYear.entrySet()) {
            integerIntegerHashedMap.put(entry.getKey(), entry.getValue());
        }
        Set<Map.Entry<Integer, Integer>> entries = integerIntegerHashedMap.entrySet();

        ThrowUtils.throwIf(submitQuestionTimesYear == null, ErrorCode.SYSTEM_ERROR, "获取失败");
        return ResultUtils.success(entries);
    }
}
